﻿using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using Asdo.Controls;

namespace Asdo.Helpers
{
    public class DragDropHelper
    {
        public DragDropHelper(UIElement dragSource)
        {
            _dragSource = dragSource;
        }

        private readonly UIElement _dragSource;
        private bool _drop;
        private bool _esc;
        private ThumbWindow _thumbWindow;

        public DragResult DoDragDrop(string format, object data)
        {
            var res = DragResult.None;

            if (_dragSource != null && data != null)
            {
                _dragSource.GiveFeedback += OnGiveFeedback;
                _dragSource.QueryContinueDrag += OnQueryContinueDrag;

                _drop = false;
                _esc = false;

                _thumbWindow = new ThumbWindow(data);
                _thumbWindow.Show();
                
                FollowMouse();

                var eff = DragDrop.DoDragDrop(_dragSource, new DataObject(format, data),
                                                             DragDropEffects.All);

                _thumbWindow.Close();
                _thumbWindow = null;

                _dragSource.QueryContinueDrag -= OnQueryContinueDrag;
                _dragSource.GiveFeedback -= OnGiveFeedback;

                Debug.WriteLine(eff);

                if (eff == DragDropEffects.None)
                {
                    res = _esc ? DragResult.Escape : DragResult.Lost;
                }
            }
            return res;
        }

        public double Top { get; private set; }
        public double Left { get; private set; }

        public void FollowMouse()
        {
            var pnt = new Point32(0, 0);

            GetCursorPos(ref pnt);

            Top = pnt.Y + 2;
            Left = pnt.X - 20;
            
            _thumbWindow.Top = Top;
            _thumbWindow.Left = Left;

        }

        internal struct Point32
        {
            public readonly int X;
            public readonly int Y;

            public Point32(int x, int y)
            {
                X = x;
                Y = y;
            }
        }

        [DllImport("user32.dll")]
        internal static extern bool GetCursorPos(ref Point32 pt);

        #region DragSource event handlers

        private void OnQueryContinueDrag(object sender, QueryContinueDragEventArgs e)
        {
            FollowMouse();
            
            if (e.EscapePressed)
            {
                _esc = true;
            }
            if (_drop)
            {
                Debug.WriteLine("DROP");
                e.Action = DragAction.Drop;
                e.Handled = true;
            }
        }

        private void OnGiveFeedback(object sender, GiveFeedbackEventArgs e)
        {
            e.UseDefaultCursors = false;
            e.Handled = true;

            if (e.Effects == DragDropEffects.Move)
            {
                Debug.WriteLine("Will DROP");
                _drop = true;
            }
        }
        
        #endregion
    }

    public enum DragResult
    {
        None,
        Escape,
        Lost,
    }

}
